home *** CD-ROM | disk | FTP | other *** search
- /*
- Re-Animator 1.1.0: Generic animation player.
-
- Written by: Russell LaValle
- Correspondence: 12-i Bimini Crossing
- Hampton, VA 23666
-
- Re-Animator is a relatively simple ( in retrospect ) PICS animation
- player. It will read any file with PICTs resources and animate them
- very quickly using CopyBits.
-
-
- Enhancements since Re-Animator 1.0.1:
- 1. The user now has the option to make the animation window appear
- on the left edge of the screen- greatly improving speed.
-
- 2. As well as displaying each frame as it's loaded in, Re-Animator
- shows a small window with a growing bar signifying its progress
- loading the file.
-
- 3. The user can have the Open dialog box display all files or just
- PICS files.
-
- 4. The speed of the animation can be selected from the menu bar.
-
- 5. Added a less boring Finder Icon, and the version resource to
- the resource file.
-
-
- One problem I found with other animation solutions using
- only DrawPicture, was that they were extremely slow. Another problem
- was when they animated certain PICTs, they didn't overwrite the
- underlying PICT on the screen with a new one- they just peformed an OR
- operation. Clearing the last PICT manually, slowed the animation even
- more. I couldn't find a share/freeware program to do this, so I wrote
- my own.
-
- This is my first "real" Macintosh program. I'll continue
- to improve it as I find/hear improvements needed.
-
- Re-Animator is Freeware. Do anything you'd like with it.
-
- I'd like to thank Dave Mark & CartWright Reed for the excellent
- Macintosh Programming Primer Volume I. Also extremely helpful were
- Brigham Stevens' offScreenBitMap.c routines. And of course, Think C is
- an awesome/inexpensive developement environment.
-
- If you have a very large animation to run, you may need to enlarge
- the application memory size in the Get Info box.
-
- Feel free to write me at the above address to comment or make
- suggestions. I can also be reached on America Online: Russell FP
-
- *************************************
- * I did not include the Proj file *
- * because it was huge with the *
- * inclusion of the ANSI library. *
- * When you create the project, just *
- * be sure to add: *
- * 1. Re-Animator.c *
- * 2. MacTraps *
- * 3. ANSI *
- *************************************
- */
-
- #include <stdlib.h>
-
- #define NIL_POINTER 0L
- #define NIL_STRING "\p"
- #define A_SECOND 60
-
- #define NOTHING NIL_STRING
- #define NO_FILTER NIL_POINTER
- #define NO_HOOK NIL_POINTER
- #define ALL_TYPES -1
-
- #define MIN_SLEEP 0L
- #define NIL_MOUSE_REGION 0L
- #define REMOVE_ALL_EVENTS 0
-
- #define RECT_LEFT 10
- #define RECT_TOP 10
- #define RECT_RIGHT 212
- #define RECT_BOTTOM 25
-
- #define PEN_HEIGHT 13
-
- #define CANT_OPEN_FILE 400
- #define CANT_GET_RES 401
- #define OUT_OF_MEMORY 402
- #define NO_WINDOW_RES 403
- #define NO_PICTS 404
-
- #define APPLE_MENU_ID 400
- #define FILE_MENU_ID 401
- #define SPEED_MENU_ID 403
- #define OPTION_MENU_ID 404
-
- #define OUR_MBAR 400
- #define PROG_WINDOW 400
-
- #define ABOUT_ITEM 1
-
- #define OPEN_ITEM 1
- #define CLOSE_ITEM 2
- #define RUN_ITEM 4
- #define QUIT_ITEM 6
-
- #define FAST_AS_POS 1
- #define ONE_SIXTIETH 2
- #define ONE_THIRTIETH 3
- #define ONE_TWENTIETH 4
- #define ONE_FIFTEENTH 5
- #define ONE_TENTH 6
- #define ONE_FIFTH 7
-
- #define SUPER_FAST 1
- #define PICS_ONLY 3
-
- #define ADD_CHECK TRUE
- #define REMOVE_CHECK FALSE
-
- #define YES_GO_AWAY TRUE
- #define MOVE_TO_FRONT -1L
- #define LEAVE_THERE FALSE
- #define VISIBLE TRUE
-
- #define ABOUT_ALERT 400
- #define ERROR_ALERT_ID 401
- #define MOTHER_ERROR "\pCan't tell what error happened... Sorry."
-
- Rect destRect, sourceRect, picRect, frame1Rect, progressRect;
- int numFrames, horizDiff, vertDiff, addFlag,
- animSpeed, lastSpeed, windRectTop, windRectLeft;
- Boolean notDone = TRUE,
- fileLoaded, doneAnimating, errorDetected, superFastFlag,
- PICSOnlyFlag;
- BitMap *theAnimation, lastBitMap;
- WindowRecord animWindRec;
- WindowPtr animateWindow, progressWindow;
- SFReply theReply;
- MenuHandle theAppleMenu, theFileMenu, theSpeedMenu, theOptionMenu;
- EventRecord theEvent;
- PicHandle thePict;
-
- /********************************** main *****************/
- main()
- {
- ToolBoxInit(); /* call initialization routines */
- MenuBarInit();
- InitProgWindow();
- Alert( ABOUT_ALERT, NIL_POINTER ); /* display initial about box */
-
- MainLoop();
- }
-
- /********************************** ToolBoxInit **********/
- ToolBoxInit()
- {
- InitGraf( &thePort ); /* standard initialization stuff */
- InitFonts();
- FlushEvents( everyEvent, 0 );
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs( NIL_POINTER );
- InitCursor();
- }
-
- /********************************** MenuBarInit **********/
- MenuBarInit()
- {
- Handle theMenuBar;
-
- theMenuBar = GetNewMBar( OUR_MBAR ); /* load the menu bar */
- SetMenuBar( theMenuBar ); /* make it active */
- theAppleMenu = GetMHandle( APPLE_MENU_ID );
- AddResMenu( theAppleMenu, 'DRVR' );
- theFileMenu = GetMHandle( FILE_MENU_ID );
- theSpeedMenu = GetMHandle( SPEED_MENU_ID );
- theOptionMenu = GetMHandle( OPTION_MENU_ID );
- lastSpeed = 1;
- CheckItem( theSpeedMenu, lastSpeed, ADD_CHECK );
- PICSOnlyFlag = TRUE;
- CheckItem( theOptionMenu, PICS_ONLY, PICSOnlyFlag );
- superFastFlag = FALSE;
- DrawMenuBar(); /* and display it */
- }
-
- /********************************** MainLoop *************/
- MainLoop()
- {
- do
- {
- errorDetected = FALSE; /* reset Error flag each time around */
- HandleEvent();
- } while ( notDone ); /* keep going until we're done */
- CloseFile(theAnimation);
- }
-
- /********************************** HandleEvent **********/
- HandleEvent()
- {
- char theKey;
-
- WaitNextEvent( everyEvent, &theEvent, /* return an event */
- MIN_SLEEP, NIL_MOUSE_REGION );
-
- switch ( theEvent.what )
- {
- case mouseDown: /* check for mouse and */
- HandleMouseDown(); /* keyboard events */
- break;
- case keyDown:
- case autoKey:
- theKey = theEvent.message & charCodeMask;
- if (( theEvent.modifiers & cmdKey ) != 0 )
- HandleMenuChoice( MenuKey( theKey ));
- break;
- case updateEvt:
- if ( ( WindowPtr )theEvent.message == animateWindow )
- {
- BeginUpdate( theEvent.message );
- DrawFrame( theAnimation );
- EndUpdate( theEvent.message );
- }
- break;
- } /* switch */
- }
-
- /********************************** HandleMouseDown ******/
- HandleMouseDown()
- {
- WindowPtr theWindow;
- short int thePart;
- long int menuChoice;
-
- thePart = FindWindow( theEvent.where, &theWindow );
- switch ( thePart )
- {
- case inMenuBar:
- menuChoice = MenuSelect( theEvent.where );
- HandleMenuChoice( menuChoice );
- break;
- case inSysWindow:
- SystemClick( &theEvent, theWindow );
- break;
- } /* case */
- }
-
- /********************************** HandleMenuChoice *****/
- HandleMenuChoice( long int menuChoice )
- {
- int theMenu, theItem;
-
- if ( menuChoice != 0 )
- {
- theMenu = HiWord( menuChoice ); /* Get which item of which */
- theItem = LoWord( menuChoice ); /* menu was selected. */
- switch ( theMenu )
- {
- case APPLE_MENU_ID:
- HandleAppleChoice( theItem );
- break;
- case FILE_MENU_ID:
- HandleFileChoice( theItem );
- break;
- case SPEED_MENU_ID:
- HandleSpeedChoice( theItem );
- break;
- case OPTION_MENU_ID:
- HandleOptionChoice( theItem );
- break;
- } /* case */
- } /* if */
- HiliteMenu( 0 );
- }
-
- /********************************** HandleAppleChoice ****/
- HandleAppleChoice( int theItem )
- {
- Str255 accName;
- int accNumber;
- short int itemNumber;
-
- switch ( theItem )
- {
- case ABOUT_ITEM:
- Alert( ABOUT_ALERT, NIL_POINTER ); /* generic alert to */
- break; /* show about info */
- default:
- GetItem( theAppleMenu, theItem, accName ); /* Get and run */
- accNumber = OpenDeskAcc( accName ); /* a DA. */
- break;
- } /* switch */
- }
-
- /********************************** HandleFileChoice *****/
- HandleFileChoice( int theItem )
- {
- switch ( theItem )
- {
- case OPEN_ITEM:
- OpenFile();
- break;
- case CLOSE_ITEM:
- CloseFile(theAnimation);
- break;
- case RUN_ITEM:
- AnimateThem();
- break;
- case QUIT_ITEM:
- notDone = FALSE;
- break;
- } /* switch */
- }
- /********************************** HandleSpeedChoice ****/
- HandleSpeedChoice( int theItem )
- {
- switch ( theItem )
- {
- case FAST_AS_POS:
- animSpeed = 0;
- break;
- case ONE_SIXTIETH:
- animSpeed = 1;
- break;
- case ONE_THIRTIETH:
- animSpeed = 2;
- break;
- case ONE_TWENTIETH:
- animSpeed = 3;
- break;
- case ONE_FIFTEENTH:
- animSpeed = 4;
- break;
- case ONE_TENTH:
- animSpeed = 6;
- break;
- case ONE_FIFTH:
- animSpeed = 12;
- break;
- } /* switch */
- CheckItem( theSpeedMenu, lastSpeed, REMOVE_CHECK );
- CheckItem( theSpeedMenu, theItem, ADD_CHECK );
- lastSpeed = theItem;
- }
- /**********************************HandleOptionChoice ****/
- HandleOptionChoice( int theItem )
- {
- switch ( theItem )
- {
- case SUPER_FAST:
- superFastFlag = !superFastFlag;
- if ( fileLoaded )
- if ( superFastFlag )
- MoveWindow( animateWindow, 0, windRectTop,
- LEAVE_THERE );
- else
- MoveWindow( animateWindow, windRectLeft, windRectTop,
- LEAVE_THERE );
- CheckItem( theOptionMenu, SUPER_FAST, superFastFlag );
- break;
- case PICS_ONLY:
- PICSOnlyFlag = !PICSOnlyFlag;
- CheckItem( theOptionMenu, PICS_ONLY, PICSOnlyFlag );
- break;
- } /* switch */
- }
-
- /********************************** OpenFile *************/
- OpenFile()
- {
- GetPicsFile();
- if (theReply.good)
- {
- LoadPics();
- if ( !( errorDetected ) ) /* If everything's */
- { /* fine, enable and */
- EnableItem( theFileMenu, CLOSE_ITEM ); /* disable certain */
- EnableItem( theFileMenu, RUN_ITEM ); /* menu items. */
- DisableItem( theFileMenu, OPEN_ITEM );
- } /* if */
- } /* if */
- }
-
- /********************************** GetPicsFile **********/
- GetPicsFile()
- {
- Point dialogLoc;
- SFTypeList fileTypes;
- int numTypes;
-
- dialogLoc.h = 80; /* set up location to place select */
- dialogLoc.v = 80; /* dialog, then set type of file to */
- fileTypes[ 0 ] = 'PICS'; /* show */
- if ( PICSOnlyFlag )
- numTypes = 1;
- else
- numTypes = ALL_TYPES;
- SFGetFile( dialogLoc, NOTHING, NO_FILTER, numTypes,
- &fileTypes, NO_HOOK, &theReply); /* Call file select */
- } /* dialog. */
-
- /********************************** CloseFile ************/
- CloseFile(BitMap *animation)
- {
- OSErr theResult;
- int i;
-
- if ( fileLoaded )
- {
- theResult = FSClose( theReply.vRefNum ); /* Close the file. */
- for ( i=0; i < numFrames; i++, animation++ )
- {
- FreeBitMap( animation ); /* Release memory. */
- } /* for */
- free( theAnimation );
- free( &lastBitMap );
- CloseWindow( animateWindow );
- fileLoaded = FALSE;
- DisableItem( theFileMenu, RUN_ITEM ); /* Enable/disable */
- DisableItem( theFileMenu, CLOSE_ITEM ); /* appropriate menu */
- EnableItem( theFileMenu, OPEN_ITEM ); /* items. */
- } /* if */
- }
-
- /********************************** LoadPics *************/
- LoadPics()
- {
- short int resRefNum;
- int i, incStep;
- BitMap *animation;
- GrafPort tempPort;
-
- if (( resRefNum = OpenRFPerm( theReply.fName, /* Open the file. */
- theReply.vRefNum, fsRdPerm )) == -1 )
- {
- ErrorHandler( CANT_OPEN_FILE );
- }
- else
- {
- numFrames = Count1Resources( 'PICT' ); /* find # of PICTs */
-
- if ( numFrames > 0 )
- {
- if ( 200 % numFrames )
- addFlag = 1;
- else
- addFlag = 0;
- theAnimation = ( BitMap * ) calloc( (unsigned)(numFrames),
- sizeof(BitMap) ); /* allocate array */
- animation = theAnimation;
- GetMyPict( 0, animation );
- GetAnimWindow( frame1Rect );
- InitProgress();
- OpenPort( &tempPort );
- NewBitMap( &frame1Rect, &lastBitMap );
- LoadPicture( animation++, 0, &tempPort );
- fileLoaded = TRUE; /* set flag */
- if ( numFrames > 1 )
- {
- for ( i=1; i < numFrames; i++, animation++ )
- {
- GetMyPict( i, animation );
- LoadPicture( animation, i, &tempPort ); /* fill fields */
- } /* for */
- } /* if */
- ClosePort( &tempPort );
- HideWindow( progressWindow );
- DrawFrame( theAnimation );
- SetPort( progressWindow );
- PaintRect( &progressRect );
- } /* if */
- else
- {
- FSClose( theReply.vRefNum ); /* if no PICTs, close file */
- ErrorHandler( NO_PICTS ); /* display error message */
- } /* else */
- } /* else */
- }
-
- /********************************** GetMyPict ***********/
- GetMyPict( int frameNum, BitMap *theMap )
- {
-
- thePict = (PicHandle)Get1IndResource( 'PICT', frameNum + 1 );
-
- if ( ResError() == resNotFound )
- {
- ErrorHandler( CANT_GET_RES );
- } /* if */
- else
- {
- picRect = ( **thePict ).picFrame;
- RemoveSpace( &picRect, frameNum );
- if ( frameNum == 0 )
- {
- frame1Rect = picRect;
- }
- NewBitMap( &frame1Rect, theMap ); /* allocate memory */
-
- if ( MemErr )
- {
- DisposHandle( thePict ); /* if not enough memory */
- ErrorHandler( OUT_OF_MEMORY ); /* display message and */
- } /* if */
- } /* else */
- }
-
- /********************************** LoadPicture **********/
- LoadPicture( BitMap *theMap, int iteration, GrafPort *tPort )
- {
- int hDraw;
-
- SetPort( tPort );
- CopyBits( &lastBitMap, theMap, &frame1Rect, &frame1Rect,
- srcCopy, NIL_POINTER );
- SetPortBits( theMap ); /* draw the PICT in */
- FillRect( &picRect, white ); /* each BitMap that */
- DrawPicture( thePict, &picRect ); /* we allocated */
- DisposHandle( thePict );
- CopyBits( theMap, &lastBitMap, &frame1Rect, &frame1Rect,
- srcCopy, NIL_POINTER );
- SetPort( animateWindow );
- DrawFrame( theMap );
- SetPort( progressWindow );
- hDraw = 200 * ( iteration + 1 ) / numFrames + RECT_LEFT + addFlag;
- LineTo ( hDraw, RECT_TOP + 1 );
- }
-
- /********************************** InitProgWindow *******/
- InitProgWindow()
- {
- progressWindow = GetNewWindow( PROG_WINDOW, NIL_POINTER,
- MOVE_TO_FRONT );
- PenMode( patCopy );
- animSpeed = 0;
- }
-
- /********************************** InitProgress *********/
- InitProgress()
- {
- SelectWindow( progressWindow );
- SetPort( progressWindow );
- SetRect ( &progressRect, RECT_LEFT, RECT_TOP,
- RECT_RIGHT, RECT_BOTTOM );
- ShowWindow( progressWindow );
- FillRect( &progressRect, white );
- PenSize( 1, 1 );
- PenPat( black );
- FrameRect ( &progressRect );
- MoveTo( 60, 40 );
- DrawString( "\pLoading PICTs...");
- MoveTo( RECT_LEFT + 1, RECT_TOP + 1 );
- PenSize( 1, PEN_HEIGHT );
- PenPat( gray );
- }
-
- /********************************** FreeBitMap ***********/
- FreeBitMap( BitMap *Bits )
- {
- DisposPtr( Bits->baseAddr ); /* free up a BitMap Ptr */
- Bits->baseAddr = NIL_POINTER; /* and it's memory */
- SetRect( &Bits->bounds, 0,0,0,0 );
- Bits->rowBytes = 0;
- }
-
- /********************************** NewBitMap ************/
- NewBitMap( Rect *frame, BitMap *theMap )
- {
- int size, rbytes;
-
- CalcOffScreen( frame, &size, &rbytes ); /* find amount of mem. */
- theMap->rowBytes = rbytes; /* to allocate, and set */
- theMap->bounds = *frame; /* up a Ptr to do that */
- theMap->baseAddr = NewPtr( size );
- }
-
- /********************************** CalcOffScreen ********/
- CalcOffScreen( frame, needed, rows )
- register Rect *frame;
- register int *needed;
- register int *rows;
- {
- *rows = (((( frame->right) - ( frame->left )) + 15)/16 ) * 2;
- *needed = (( *rows ) * (( frame->bottom ) - ( frame->top )));
- }
-
- /********************************** GetAnimWindow ************/
- GetAnimWindow( Rect theRect )
- {
- Rect windRect;
-
- sourceRect = theRect;
- destRect = theRect;
-
- GetContent( &windRect );
- ClipPicOrWindow( &windRect );
- windRectTop = windRect.top;
- windRectLeft = windRect.left;
- if ( superFastFlag )
- OffsetRect( &windRect, -( windRect.left ), 0 );
- animateWindow = NewWindow( &animWindRec, &windRect, "\pRe-Animator",
- VISIBLE, plainDBox, MOVE_TO_FRONT,
- YES_GO_AWAY, 8 );
- }
- /********************************** GetContent ***********/
- GetContent(Rect *windRect)
- {
- *windRect = screenBits.bounds; /* determine a baseline */
- windRect->top += ( MBarHeight + 2 ); /* window size by coming in */
- windRect->bottom -= 2; /* from top ( top + MBAR ) */
- /* and bottom. */
- }
-
- /********************************** ClipPicOrWindow ******/
- ClipPicOrWindow( Rect *windRect)
- {
- int windWidth, windHeight,
- rectWidth, rectHeight;
- windWidth = windRect->right - windRect->left;
- windHeight = windRect->bottom - windRect->top;
- rectWidth = sourceRect.right;
- rectHeight = sourceRect.bottom;
-
- if ( rectWidth > windWidth )
- {
- sourceRect.left = ( rectWidth - windWidth )/2; /* clip center */
- sourceRect.right = sourceRect.left + windWidth; /* of picture */
- destRect.right = windWidth; /* horizontally */
- } /* if */
- else
- {
- windRect->left += ( windWidth - rectWidth )/2; /* size window */
- windRect->right = windRect->left + rectWidth; /* horizontally */
- } /* else */
-
- if ( rectHeight > windHeight )
- {
- sourceRect.top = ( rectHeight - windHeight )/2; /* clip center */
- sourceRect.bottom = sourceRect.top + windHeight; /* of picture */
- destRect.bottom = windHeight; /* vertically */
- } /* if */
- else
- {
- windRect->top += ( windHeight - rectHeight )/2; /* size window */
- windRect->bottom = windRect->top + rectHeight; /* vertically */
- } /* else */
- }
-
- /********************************** RemoveSpace **********/
- RemoveSpace( Rect *theRect, int frameNum )
- {
- if ( frameNum == 0 )
- {
- horizDiff = theRect->left;
- vertDiff = theRect->top;
- }
- OffsetRect( theRect, -horizDiff, -vertDiff );
- }
-
- /********************************** AnimateThem **********/
- AnimateThem()
- {
- int i;
- long int endTicks;
- BitMap *animation;
-
- if ( fileLoaded )
- {
- doneAnimating = FALSE;
- SetPort( progressWindow );
- HideCursor();
- do
- {
- for ( i=0, animation = theAnimation; i < numFrames;
- i++, animation++) /* run through PICS */
- {
- endTicks = TickCount() + animSpeed;
- DrawFrame( animation );
- if ( animSpeed > FAST_AS_POS )
- while ( TickCount() < endTicks );
- if ( Button() )
- {
- doneAnimating = TRUE;
- break;
- } /* if */
- } /* for */
- } while ( !( doneAnimating )); /* til mouse button pressed */
- ShowCursor();
- } /* if */
- }
- /********************************** DrawFrame ************/
- DrawFrame( BitMap *theMap )
- {
- CopyBits( theMap, /* from BitMap */
- &( animWindRec.port.portBits ), /* to BitMap */
- &sourceRect, /* from Rect */
- &destRect, /* to Rect */
- srcCopy, /* xfer mode */
- NIL_POINTER ); /* mask region */
- }
-
- /********************************** ErrorHandler *********/
- ErrorHandler( int stringNum )
- {
- StringHandle errorStringH;
-
- if (( errorStringH = GetString( stringNum )) == NIL_POINTER )
- ParamText( MOTHER_ERROR, NIL_STRING, NIL_STRING,
- NIL_STRING ); /* If we can't find error message, */
- else /* show panic message. */
- {
- HLock( errorStringH ); /* find error message to display */
- ParamText( *errorStringH, NIL_STRING, NIL_STRING, NIL_STRING );
- HUnlock( errorStringH );
- }
- StopAlert( ERROR_ALERT_ID, NIL_POINTER ); /* show alert, and */
- errorDetected = TRUE; /* set flag */
- ExitToShell();
- }